<

モーダル ルートのオーバーレイ エントリのセマンティクス順序

まとめ

モーダル ルートのオーバーレイ エントリのセマンティクスのトラバース順序を変更しました。 アクセシビリティのトークバックまたはボイスオーバーがモーダル ルートの範囲に焦点を当てるようになりました まずモーダルバリアの代わりに。

コンテクスト

モーダル ルートには、スコープとモーダル バリアという 2 つのオーバーレイ エントリがあります。の スコープはモーダル ルートの実際の内容であり、モーダル バリアは スコープが画面全体をカバーしていない場合は、ルートの背景。もし モーダル ルートは true を返しますbarrierDismissible、モーダルバリアは次のようになります。 ユーザーはモーダル バリアをタップして、 モーダルルート。この変更により、特に範囲を絞り込むためのアクセシビリティが強化されました。 まずはモーダルバリアの前。

変更内容の説明

両方の上に追加のセマンティクス ノードを追加しました モーダルルートのオーバーレイエントリ。 これらのセマンティクス ノードはセマンティクスを示します。 これら 2 つのオーバーレイ エントリの順序を調べます。 これにより、セマンティクス ツリーの構造も変更されました。

移行ガイド

更新後のセマンティクス ツリーの変更が原因でテストが失敗し始めた場合は、 モーダルルートの上に新しいノードができることを期待してコードを移行できます オーバーレイエントリ。

移行前のコード:

import 'dart:ui';

import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/material.dart';

void main() {
  testWidgets('example test', (WidgetTester tester) async {
    final SemanticsHandle handle =
        tester.binding.pipelineOwner.ensureSemantics();

    // Build our app and trigger a frame.
    await tester.pumpWidget(MaterialApp(home: Scaffold(body: Text('test'))));

    final SemanticsNode root =
        tester.binding.pipelineOwner.semanticsOwner.rootSemanticsNode;

    final SemanticsNode firstNode = getChild(root);
    expect(firstNode.rect, Rect.fromLTRB(0.0, 0.0, 800.0, 600.0));

    // Fixes the test by expecting an additional node above the scope route.
    final SemanticsNode secondNode = getChild(firstNode);
    expect(secondNode.rect, Rect.fromLTRB(0.0, 0.0, 800.0, 600.0));

    final SemanticsNode thirdNode = getChild(secondNode);
    expect(thirdNode.rect, Rect.fromLTRB(0.0, 0.0, 800.0, 600.0));
    expect(thirdNode.hasFlag(SemanticsFlag.scopesRoute), true);

    final SemanticsNode forthNode = getChild(thirdNode);
    expect(forthNode.rect, Rect.fromLTRB(0.0, 0.0, 56.0, 14.0));
    expect(forthNode.label, 'test');
    handle.dispose();
  });
}

SemanticsNode getChild(SemanticsNode node) {
  SemanticsNode child;
  bool visiter(SemanticsNode target) {
    child = target;
    return false;
  }

  node.visitChildren(visiter);
  return child;
}

移行後のコード:

import 'dart:ui';

import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/material.dart';

void main() {
  testWidgets('example test', (WidgetTester tester) async {
    final SemanticsHandle handle =
        tester.binding.pipelineOwner.ensureSemantics();

    // Build our app and trigger a frame.
    await tester.pumpWidget(MaterialApp(home: Scaffold(body: Text('test'))));

    final SemanticsNode root =
        tester.binding.pipelineOwner.semanticsOwner.rootSemanticsNode;

    final SemanticsNode firstNode = getChild(root);
    expect(firstNode.rect, Rect.fromLTRB(0.0, 0.0, 800.0, 600.0));

    // Fixes the test by expecting an additional node above the scope route.
    final SemanticsNode secondNode = getChild(firstNode);
    expect(secondNode.rect, Rect.fromLTRB(0.0, 0.0, 800.0, 600.0));

    final SemanticsNode thirdNode = getChild(secondNode);
    expect(thirdNode.rect, Rect.fromLTRB(0.0, 0.0, 800.0, 600.0));
    expect(thirdNode.hasFlag(SemanticsFlag.scopesRoute), true);

    final SemanticsNode forthNode = getChild(thirdNode);
    expect(forthNode.rect, Rect.fromLTRB(0.0, 0.0, 56.0, 14.0));
    expect(forthNode.label, 'test');
    handle.dispose();
  });
}

SemanticsNode getChild(SemanticsNode node) {
  SemanticsNode child;
  bool visiter(SemanticsNode target) {
    child = target;
    return false;
  }

  node.visitChildren(visiter);
  return child;
}

タイムライン

リリースされたバージョン: 1.19.0
安定版リリース: 1.20

参考文献

API ドキュメント:

  • ModalRoute
  • OverlayEntry

関連する問題:

  • 問題 46625

関連する PR:

  • PR 59290